home *** CD-ROM | disk | FTP | other *** search
- /*
- SF ClickOut.c
-
- Example extension. Demonstrates use of PatchWorks trap patching
- system to patch InitApplication. Uses new GenericPatch class.
-
- by Christopher Evans.
-
- © 1994 Natural Intelligence, Inc.
- */
-
- #include <string.h>
- #include <Notification.h>
- #include <Traps.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stddef.h>
- #include <Processes.h>
- #include <GestaltEqu.h>
- #include <Exception.h>
- #include <Extension.h>
- #include <GenericPatch.h>
- #include "SF ClickOut.h"
- #include <SetupA4.h>
- #include <LowMem.h>
-
-
- static Pack3Patch *thePatch = 0;
- static SystemEventPatch *sePatch = 0;
- static CloseWindowPatch *cwPatch = 0;
- static BringToFrontPatch *btfPatch = 0;
-
- #define optionKeyCode 0x003a
-
- void ShowIconFamily(short which);
-
- extern pascal short NewDialogHook(short item, DialogPtr theDialog, void *yourDataPtr);
- extern pascal short OldDialogHook(short item, DialogPtr theDialog);
- extern void StandardToSFReply(StandardFileReply *newStyle, SFReply *oldStyle);
- pascal OSErr DataSelector(OSType selector, long *response);
- void InstallSelector(void);
-
- static int dprintf(const char* format, ...);
- Boolean IsPressed(unsigned short k);
-
- CloseWindowPatch::CloseWindowPatch()
- {
- // initialize instance variables.
- eventPatch = sePatch;
-
- // install the appropriate patch.
- GenericPatch::InitGenericPatch(_CloseWindow, sizeof(CloseWindowParameters));
- Install();
- }
-
- void CloseWindowPatch::Behavior()
- {
- CloseWindowParameters* params;
-
- WindowPeek front, tmpFinderWindow;
-
-
- params = (CloseWindowParameters*)itsFrame->parameters;
-
- if(params->theWindow == eventPatch->frontFinderWindow) {
- eventPatch->frontFinderWindow = ((WindowPeek)params->theWindow)->nextWindow;
- }
- }
-
- BringToFrontPatch::BringToFrontPatch()
- {
- // initialize instance variables.
- GetIndString(finderName,128,1);
- eventPatch = sePatch;
-
- // install the appropriate patch.
- GenericPatch::InitGenericPatch(_BringToFront, sizeof(BringToFrontParameters));
- Install();
- }
-
-
- BringToFrontPatch::~BringToFrontPatch()
- {
-
- }
-
-
-
- void BringToFrontPatch::Behavior()
- {
- BringToFrontParameters* params;
-
- WindowPeek front, tmpFinderWindow;
-
-
- params = (BringToFrontParameters*)itsFrame->parameters;
-
- if( *((long *)LMGetCurApName()) == *((long *)finderName) ) {
- if(EqualString(LMGetCurApName(), finderName, FALSE, FALSE)) {
- eventPatch->frontFinderWindow = params->itsWindow;
- }
- }
- }
-
-
- SystemEventPatch::SystemEventPatch()
- {
- // initialize instance variables.
- GetIndString(finderName,128,1);
- pack3Patch = thePatch;
- frontFinderWindow = NULL;
-
- // install the appropriate patch.
- GenericPatch::InitGenericPatch(_SystemEvent, sizeof(SystemEventParameters));
- Install();
- }
-
- void SystemEventPatch::Behavior()
- {
- SystemEventParameters* params;
-
- EventRecord *evt;
- WindowPeek front, tmpFinderWindow;
- Handle wRefCon, windowInfo;
- GrafPtr savePort;
- Point mousePoint, localPoint;
- long dirID;
- short vRefNum, *shortPtr;
- StringPtr curAp = LMGetCurApName();
-
- params = (SystemEventParameters*)itsFrame->parameters;
- evt = params->theEvt;
-
-
- if( *((long *)curAp) == *((long *)finderName) ) {
- if(EqualString(curAp, finderName, FALSE, FALSE)) {
- frontFinderWindow = (WindowPtr)LMGetWindowList();
- }
- }
-
- //After it is set, check for mouse downs. outside of SF dialogs.
- if(evt->what == mouseDown) {
-
-
- front = (WindowPeek)FrontWindow(); //Get the current front window
- if(front!= NULL) { //If we got a window
- wRefCon = (Handle)GetWRefCon(front); //Grab its refcon
- if(wRefCon == (Handle)0x73746466) { //We're in an SF dialog
- BlockMove(&evt->where, &mousePoint, 4);
- localPoint = mousePoint;
- GetPort(&savePort);
- SetPort(front);
- GlobalToLocal(&localPoint);
- if(!PtInRect(localPoint, &front->port.portRect)) {
- tmpFinderWindow = frontFinderWindow;
- while( tmpFinderWindow != NULL) {
- wRefCon = (Handle)GetWRefCon(tmpFinderWindow);
- if(wRefCon != 0) {
- localPoint = mousePoint;
-
- SetPort(tmpFinderWindow);
- GlobalToLocal(&localPoint);
- if(PtInRect(localPoint, &tmpFinderWindow->port.portRect)) {
- windowInfo = (char *)*wRefCon + 8;
- if(windowInfo) {
- windowInfo = *windowInfo;
- windowInfo = *windowInfo + 0x00000030;
- dirID = (long)*windowInfo;
- windowInfo +=1;
- shortPtr = (short *)windowInfo;
- vRefNum = (short)*shortPtr;
- pack3Patch->SetDirectory(dirID, vRefNum);
-
- evt->what = nullEvent;
- break;
- }
- }
- }
- tmpFinderWindow = tmpFinderWindow->nextWindow;
- }
- }
- SetPort(savePort);
- }
- }
- }
-
-
- }
-
-
-
- Pack3Patch::Pack3Patch()
- {
- SysEnvRec theSERec;
- CursHandle cursH1, cursH2;
- Size cs1, cs2;
- short tmpShort;
-
- // initialize instance variables.
- nextDirID = 0;
- nextVRefNum = 0;
-
- // install the appropriate patch.
- GenericPatch::InitGenericPatch(_Pack3, sizeof(CustomGetParameters));
- Install();
- }
-
- Pack3Patch::~Pack3Patch()
- {
-
- }
-
- void Pack3Patch::Behavior()
- {
- Pack3Parameters *params = (Pack3Parameters*)itsFrame->parameters;
- SFPutParameters *sfputParams;
- SFPPutParameters *sfpputParams;
- SFGetParameters *sfgetParams;
- SFPGetParameters *sfpgetParams;
- StandardPutParameters *standardPutParams;
- StandardGetParameters *standardGetParams;
- CustomPutParameters *customPutParams;
- CustomGetParameters *customGetParams;
- Point where = {-1,-1};
- Point oldWhere = {100,100};
-
-
- switch(params->itsMethod) {
- case 1: //SFPutFile
- sfputParams = (SFPutParameters*)itsFrame->parameters;
- oldFilter = sfputParams->dlgHook;
- sfputParams->dlgHook = OldDialogHook;
- replyPtr = sfputParams->reply;
-
- break;
-
- case 2: //SFGetFile
- sfgetParams = (SFGetParameters*)itsFrame->parameters;
-
- oldFilter = sfgetParams->dlgHook;
- sfgetParams->dlgHook = OldDialogHook;
- replyPtr = sfgetParams->reply;
-
- break;
-
- case 3: //SFPPutFile
- sfpputParams = (SFPPutParameters*)itsFrame->parameters;
-
- oldFilter = sfpputParams->dlgHook;
- sfpputParams->dlgHook = OldDialogHook;
- replyPtr = sfpputParams->reply;
- break;
-
- case 4: //SFPGetFile
- sfpgetParams = (SFPGetParameters*)itsFrame->parameters;
-
- oldFilter = sfpgetParams->dlgHook;
- sfpgetParams->dlgHook = OldDialogHook;
- replyPtr = sfpgetParams->reply;
- break;
-
- case 5: //StandardPutFile
- standardPutParams = (StandardPutParameters*)itsFrame->parameters;
-
- {
- CustomPutPack3ProcPtr proc;
- proc = (CustomPutPack3ProcPtr)this->itsOld;
-
- proc(standardPutParams->prompt,standardPutParams->defaultName,standardPutParams->reply,sfPutDialogID,where,NewDialogHook,NULL,NULL,NULL,this, 7);
-
- /*
- An exercise left to the reader...
-
- Open the folder in the finder when the option key is pressed
- down and a file selected, this way if it isn't openned, they can
- also see where the file went. (Remember, the file might not exist
- yet...)
- */
- // if( (standardPutParams->reply->sfGood) && (IsPressed(optionKeyCode))) {
- // OpenSelection(true, &standardPutParams->reply->sfFile);
- // }
- }
-
- AbortTrap();
- break;
-
- case 6: //StandardGetFile
- standardGetParams = (StandardGetParameters*)itsFrame->parameters;
-
- {
- CustomGetPack3ProcPtr proc;
- proc = (CustomGetPack3ProcPtr)this->itsOld;
- this->oldFileFilter = standardGetParams->fileFilter;
-
- proc(CustomFileFilter,standardGetParams->numTypes,standardGetParams->typeList,standardGetParams->reply,sfGetDialogID,where,NewDialogHook,NULL,NULL,NULL,this, 8);
-
- // if( (standardGetParams->reply->sfGood) && (IsPressed(optionKeyCode))) {
- // OpenSelection(true, &standardGetParams->reply->sfFile);
- // }
- }
- AbortTrap();
- break;
-
- case 7: //CustomPutFile
- customPutParams = (CustomPutParameters*)itsFrame->parameters;
-
- oldFilter = customPutParams->dlgHook;
- customPutParams->dlgHook = NewDialogHook;
- theirDataPtr = customPutParams->yourDataPtr;
- replyPtr = customPutParams->reply;
- customPutParams->yourDataPtr = (void *)this;
- break;
-
- case 8: //CustomGetFile
- customGetParams = (CustomGetParameters*)itsFrame->parameters;
-
- oldFilter = customGetParams->dlgHook;
- customGetParams->dlgHook = NewDialogHook;
- theirDataPtr = customGetParams->yourDataPtr;
- replyPtr = customGetParams->reply;
- customGetParams->yourDataPtr = (void *)this;
- break;
- }
- nextDirID = 0;
- nextVRefNum = 0;
- }
-
-
- void Pack3Patch::SetDirectory(long dirID, short vRefNum)
- {
- nextDirID = dirID;
- nextVRefNum = vRefNum;
- }
-
- pascal Boolean CustomFileFilter(ParmBlkPtr param, void *myData)
- {
- Pack3Patch *p3patch = (Pack3Patch *)myData;
- FileFilterProcPtr newProc = p3patch->oldFileFilter;
-
- if(newProc==nil) return FALSE;
-
- return (newProc(param));
-
- }
-
- pascal short NewDialogHook(short item, DialogPtr theDialog, void *yourDataPtr)
- {
- StandardFileReply *replyPtr;
- Pack3Patch *myObject;
-
- myObject = (Pack3Patch *)yourDataPtr;
- replyPtr = (StandardFileReply *)myObject->replyPtr;
-
- if (myObject->nextDirID != 0) {
- item = sfHookChangeSelection;
- replyPtr->sfFile.vRefNum = myObject->nextVRefNum; // re-aim standard file at root
- replyPtr->sfFile.parID = myObject->nextDirID;
- replyPtr->sfFile.name[0] = 0;
-
- myObject->nextDirID = 0;
- myObject->nextVRefNum = 0;
- }
- else {
- dlgHookProc oldDlgHook = myObject->oldFilter;
-
- if(oldDlgHook != NULL) {
- item = oldDlgHook(item, theDialog, myObject->theirDataPtr);
- }
- }
- return item;
- }
-
- pascal short OldDialogHook(short item, DialogPtr theDialog)
- {
- OSErr gestaltErr;
- long gestaltResponse;
- Pack3Patch *myObject;
- gestaltErr = Gestalt('QsfQ', &gestaltResponse);
-
- if((gestaltErr == noErr) && (gestaltResponse != 0)) {
-
- myObject = (Pack3Patch *)gestaltResponse;
-
- if (myObject->nextDirID != 0) {
- item = sfHookRebuildList; // re-aim standard file at root
- LMSetCurDirStore(myObject->nextDirID);// side-effect is, volume name won't be changed
- LMSetSFSaveDisk(-(myObject->nextVRefNum)); // in upper-right corner...
-
- myObject->nextDirID = 0;
- myObject->nextVRefNum = 0;
- }
- else {
- oldDlgHookProc oldDlgHook = myObject->oldFilter;
-
- if(oldDlgHook != NULL) {
- item = oldDlgHook(item, theDialog);
- }
- }
- }
-
- return item;
- }
-
-
- //
- // Install routine. This is where you allocate your patch objects.
- // Throw an exception if something fails.
- //
- void Install()
- {
- long theSize;
- short doIt;
-
- RememberA4();
- #ifndef CDEV
- try {
- //Read preferences to see if we should load
- // if extension succeeds, show happy icon.
- thePatch = new Pack3Patch;
- sePatch = new SystemEventPatch;
- cwPatch = new CloseWindowPatch;
- btfPatch = new BringToFrontPatch;
- InstallSelector();
- ShowIconFamily(128);
- } catch {
- // extension failed, show sad icon.
- ShowIconFamily(129);
- throw(theException);
- }
- #endif CDEV
- }
-
- //
- // Remove routine. This is called when system is shutdown.
- // Perhaps this should be removed. Rob thinks it shouldn't even be
- // part of the design.
- //
-
- void Remove()
- {
- Patch::RemoveAll();
- }
-
- //
- // debugging printf.
- //
-
- static int dprintf(const char* format, ...)
- {
- va_list args;
- static char str[256];
- int count;
-
- #ifndef CDEV
- va_start(args, format);
- count = vsprintf(str, format, args);
- va_end(args);
- DebugStr(c2pstr(str));
- #endif CDEV
-
- return count;
- }
-
- Boolean IsPressed(unsigned short k)
- /*
- * Check to see if key number k is currently held down
- */
- {
- unsigned char km[16];
-
- GetKeys(km); //Get the KeyMap
- return((km[k>>3]>>(k&7))&1); //Check required bit
- }
-
-
-
- pascal OSErr DataSelector(OSType selector, long *response);
- void InstallSelector(void);
-
- void InstallSelector(void)
- {
- OSErr theErr;
- Handle gestFuncH;
- ProcPtr oldGestaltFunc;
- Str255 theNumStr;
-
- theErr = NewGestalt('QsfQ', (ProcPtr)DataSelector);
- if(theErr != noErr) {
- theErr = ReplaceGestalt('QsfQ', (ProcPtr)DataSelector, oldGestaltFunc);
- }
- }
-
- pascal OSErr DataSelector(OSType selector, long *response)
- {
- SetUpA4();
- *response = (long)thePatch;
- RestoreA4();
- return noErr;
- }
-
-
-